Skip to main content

Truck Loading

The first problem is to find the optimal packaging of products in vehicles (trucks in this example) so that

  • Minimum number of trucks are used

  • Maximum volume is ocupied by the products collectively in all the trucks

This is with the reasonable assumption that trucks with more capacity will cost more, so in case two trucks can fully accomodate a set of items, the smaller one will be preferred.

Tech Stack

Library used for optimal bin-packing is py3dbp

More specifically, a modified version of py3dbp which allows color coded images of trucks with deliveries was used.

Code snippet

from py3dbp import Packer, Bin, Item, Painter
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

def get_optimum(stats):
unfitted = min(stats, key=lambda x: x[2])[2]
stats = [stat for stat in stats if stat[2] == unfitted]
optimum = max(stats, key=lambda x: x[1])
return optimum

def process_items(deliveries, trucks):
delivery_color, color_list, color_index = [], ["yellow", "green", "blue", "pink", "red"], 0
packer = Packer()
for t in trucks:
packer.addBin(Bin(t["name"], (t["length"], t["width"], t["height"]), t["weight"], 0, 0))
for item in deliveries:
for i in range(item.num_cases):
packer.addItem(
Item(
partno=i,
name=item.delivery_number,
typeof="cube",
WHD=(item.length, item.width, item.height),
weight=1,
level=1,
loadbear=100,
updown=True,
color=color_list[color_index],
)
)
delivery_color.append([item.delivery_number, color_list[color_index]])
if color_index == len(color_list) - 1:
color_index = 0
else:
color_index += 1

packer.pack(
bigger_first=True,
distribute_items=False,
fix_point=True,
check_stable=True,
support_surface_ratio=0.75,
number_of_decimals=0,
)

packer.putOrder()
stats = []
for i in range(len(packer.bins)):
b = packer.bins[i]
vol_used = 0
for item in b.items:
vol_used += float(item.getVolume())
stats.append([i, round((vol_used / float(b.getVolume())) * 100, 2), len(b.unfitted_items)])

optimum = get_optimum(stats)
bin = packer.bins[optimum[0]]

painter = Painter(bin)
fig = painter.plotBoxAndItems(title=bin.partno, alpha=0.8, write_num=False, fontsize=20)
grid_size = 8
x, y, z = np.indices((grid_size, grid_size, grid_size))
cube = (x >= 2) & (x < 6) & (y >= 2) & (y < 6) & (z >= 2) & (z < 6)
voxelarray = cube
colors = np.empty(voxelarray.shape, dtype=object)
colors[cube] = "blue"
plt.savefig("public/truck.png")
plt.close("all")
return optimum[1], optimum[2], delivery_color